Skip to content

EFA GDA: a Put always posts at least one WQE - #43

Merged
akkart-aws merged 1 commit into
amazon-contributing:stagingfrom
akkart-aws:fix_must_ring_case
Aug 4, 2026
Merged

EFA GDA: a Put always posts at least one WQE#43
akkart-aws merged 1 commit into
amazon-contributing:stagingfrom
akkart-aws:fix_must_ring_case

Conversation

@akkart-aws

Copy link
Copy Markdown
Collaborator

Description

putImplMode skipped the post entirely for a put with no payload and no signal/counter (hasPayload || needsSignalEp gate): with nothing to deliver and nothing to tick, the operation looked like a no-op and was silently dropped.

That was an as-if optimization from before request aggregation existed, and aggregation broke its premise. With
ncclGinOptFlagsAggregateRequests, a put carries a LOCAL side effect: its non-aggregated doorbell rendezvous in postRdmaWrite is what publishes earlier deferred WQEs on the QP. Dropping "empty" puts therefore made a deferred stream impossible to terminate when its last real put happened to be aggregated -- the tail WQEs (and their signals) were never handed to the NIC and the peer waited forever.

Change the contract so a Put always posts at least one WQE. The empty case degenerates to a 0-byte write to the peer's per-context scratch via the peer DATA endpoint (target slot 0), which binds no FI_REMOTE_WRITE -- remotely unobservable; locally the doorbell rendezvous runs and submitted_count/FI_WRITE tick in lockstep, so Flush accounting stays exact.

putImplMode skipped the post entirely for a put with no payload and no
signal/counter (hasPayload || needsSignalEp gate): with nothing to
deliver and nothing to tick, the operation looked like a no-op and was
silently dropped.

That was an as-if optimization from before request aggregation existed,
and aggregation broke its premise. With
ncclGinOptFlagsAggregateRequests, a put carries a LOCAL side effect:
its non-aggregated doorbell rendezvous in postRdmaWrite is what
publishes earlier deferred WQEs on the QP. Dropping "empty" puts
therefore made a deferred stream impossible to terminate when its last
real put happened to be aggregated -- the tail WQEs (and their signals)
were never handed to the NIC and the peer waited forever.

Change the contract so a Put always posts at least one WQE. The empty
case degenerates to a 0-byte write to the peer's per-context scratch
via the peer DATA endpoint (target slot 0), which binds no
FI_REMOTE_WRITE -- remotely unobservable; locally the doorbell
rendezvous runs and submitted_count/FI_WRITE tick in lockstep, so Flush
accounting stays exact.

Signed-off-by: Arun Karthik <akkart@amazon.com>

@anshumang anshumang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With aggregate flag in put, flush needs to ring doorbell to guarantee that the sender's buffers can be reused. I think we should add a doorbell ring in flush which is already in the slow path than add an extra doorbell ring in the fast path, that is, put. Say, the user calls put with zero payload + counter + signal + aggregate off twice. Ringing the doorbell in the first call is required, what this PR addresses. But the ringing in the second call is redundant and adds latency. Although, this seems like a sub-optimally use of EFA GDA at the user level, but better to make the user pay the penalty with suboptimal flush than suboptimal put.

@akkart-aws
akkart-aws merged commit 97fb5ab into amazon-contributing:staging Aug 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants